package com.fattyCorps.common.packet;

import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;

import java.util.*;

@Data
public class PacketMap<T extends PacketElem> implements Cloneable {
    private HashMap<Integer, T> map = new HashMap<>();
    private int nId = 0;

    @JSONField(serialize = false)
    private List<T> readList = null;

    @JSONField(serialize = false)
    public List<T> getElems() {
        if (readList == null) {
            synchronized (map) {
                if (readList == null) {
                    readList = new ArrayList<>();
                    Iterator<Map.Entry<Integer, T>> iterator = map.entrySet().iterator();
                    while (iterator.hasNext()) {
                        Map.Entry<Integer, T> next = iterator.next();
                        try {
                            readList.add((T) next.getValue().clone());
                        } catch (CloneNotSupportedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                }
            }
        }

        return readList;
    }

    // 增加一个元素，有id就覆盖，没有id就增加
    public T put(T elem) {
        synchronized (map) {
            if (verifyId(elem.getId())) {
                map.put(elem.getId(), elem);
            } else {
                int index = 1;
                while (true) {
                    nId++;
                    if (nId > maxId()) {
                        nId = minId();
                    }

                    if (map.get(nId) == null) {
                        map.put(nId, elem);
                        elem.setId(nId);
                        break;
                    }

                    index++;
                    if (index > maxId()) {
                        throw new RuntimeException("error max id");
                    }
                }
            }

            readList = null;
            return elem;
        }
    }

    public T get(int id) {
        return get(id, true);
    }

    public T get(int id, boolean modify) {
        synchronized (map) {
            if (modify) {
                readList = null;
            }

            return map.get(id);
        }
    }

    public void remove(int id) {
        synchronized (map) {
            map.remove(id);
            readList = null;
        }
    }

    @Override
    public PacketMap<T> clone() throws CloneNotSupportedException {
        PacketMap objClone = (PacketMap)super.clone();
        objClone.map = new HashMap();
        Iterator<Map.Entry<Integer, T>> iterator = map.entrySet().iterator();
        while(iterator.hasNext()) {
            Map.Entry<Integer, T> next = iterator.next();
            Object clone = ((T) next.getValue()).clone();
            objClone.map.put(next.getKey(), clone);
        }

        return objClone;
    }

    private boolean verifyId(int id) {
        return id > minId() && id <= maxId();
    }

    private int maxId() {
        return 65535;
    }

    private int minId() {
        return 1;
    }
}
